<template>
  <div class="calendar-schedule">
    <h1 style="margin: 0;">赛事日历</h1>
    <p>选择赛事类型、届数和开始报名时间后，可生成赛程并将配置提交到match_data</p>
    <!-- 控制面板 -->
    <div class="control-panel">
      <el-row v-for="(row, index) in formRows" :key="index" :gutter="20" align="middle" style="margin-bottom: 12px;">
        <el-col :span="5">
          <div style="display: flex; align-items: center; gap: 8px;">
            <span class="form-label">选择赛事类型</span>
            <el-select v-model="row.genType" placeholder="选择类型" style="flex: 1;">
              <el-option v-for="opt in getAvailableTypes(index)" :key="opt.value" :label="opt.label" :value="opt.value" />
            </el-select>
          </div>
        </el-col>

        <el-col :span="5">
          <div style="display: flex; align-items: center; gap: 8px;">
            <span class="form-label">选择届数</span>
            <el-input-number v-model="row.seasonNumber" placeholder="期数" :min="1" :max="100" :precision="0"
              controls-position="right" style="flex: 1;" />
          </div>
        </el-col>

        <el-col :span="6">
          <div style="display: flex; align-items: center; gap: 8px;">
            <span class="form-label">报名开始时间</span>
            <el-date-picker v-model="row.selectedDate" type="date" placeholder="选择赛程开始日期" format="YYYY/MM/DD"
              value-format="YYYY-MM-DD" style="flex: 1;" />
          </div>
        </el-col>

        <el-col :span="8" style="display: flex; justify-content: flex-start; gap: 12px;">
          <el-button type="primary" @click="fetchScheduleDataAt(index)" :loading="row.loading" :disabled="!isFormValidAt(index)">
            预览生成赛程
          </el-button>
          <el-button
            v-if="index === formRows.length - 1 && hasMoreTypeOptions()"
            type="success"
            :disabled="!row.hasPreviewedSuccessfully"
            @click="addRow"
          >
            增加一行
          </el-button>
        </el-col>

        <!-- 最后一行下方放置全局提交log与提交按钮（使用栅格避免覆盖） -->
        <el-col v-if="index === formRows.length - 1" :span="24" style="margin-top: 8px;">
          <el-row :gutter="20" align="middle">
          <el-col :span="2">
              <span class="form-label">提交log</span>
            </el-col>
            <el-col :span="14">
              <el-input
                v-model="globalTapdUrl"
                placeholder="示例: 【1024】 --story=1409624 --user=张三 【玩法社交】 第十届星火联赛 ..."
                type="text"
                clearable
                style="width: 100%;"
                :class="{ 'url-valid': globalTapdUrl && isGlobalUrlValid, 'url-invalid': globalTapdUrl && !isGlobalUrlValid }"
              />
            </el-col>
            <el-col :span="7" style="display: flex; justify-content: flex-start;">
              <el-button type="warning" @click="genScheduleDataGlobal" :loading="globalLoading" :disabled="globalLoading">
                提交至配置表
              </el-button>
            </el-col>
          </el-row>
        </el-col>
      </el-row>
    </div>


    <!-- <el-calendar :range="[new Date(2019, 2, 4), new Date(2019, 4, 24)]" /> -->

    <!-- 日历组件 -->
    <div class="calendar-container" v-if="calendarData.length > 0">
      <el-calendar v-model="calendarValue" :range="calendarRange" :first-day-of-week="1">
        <template #date-cell="{ data }">
          <div class="calendar-cell">
            <p :class="data.isSelected ? 'is-selected' : ''">
              {{ formatDateDisplay(data.day) }}
            </p>
            <!-- 显示调度数据（同一天多个事件） -->
            <div v-if="getSchedulesForDate(data.day).length" class="schedule-list">
              <el-tag
                v-for="(item, idx) in getSchedulesForDate(data.day).slice(0, maxVisiblePerCell)"
                :key="idx"
                size="small"
                type="success"
              >
                {{ getScheduleName(item) }} {{ formatTimeHM(item.timestamp) }}
              </el-tag>

              <el-popover
                v-if="getSchedulesForDate(data.day).length > maxVisiblePerCell"
                placement="bottom"
                trigger="hover"
                width="260"
              >
                <template #reference>
                  <el-tag size="small" type="info">+{{ getSchedulesForDate(data.day).length - maxVisiblePerCell }}</el-tag>
                </template>
                <div class="popover-list">
                  <div v-for="(item, i) in getSchedulesForDate(data.day)" :key="i" class="popover-item">
                    <span class="schedule-name">{{ getScheduleName(item) }}</span>
                    <span class="schedule-time">{{ formatTimestamp(item.timestamp) }}</span>
                  </div>
                </div>
              </el-popover>
            </div>
          </div>
        </template>
      </el-calendar>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, inject, watch } from 'vue'
import { ElMessage } from 'element-plus'
import type { Axios } from 'axios'
import { CombatCalendarScheduleNameMapping } from './CombatCalendarScheduleEmun'

// 注入全局axios实例
const http = inject<Axios>('http')

// 赛事类型基础选项
const baseTypeOptions = [
  { label: '星火', value: '1' },
  { label: '封神', value: '2' },
  { label: '服战', value: '3' },
  { label: '烽火', value: '4' },
]

// 多行表单数据
interface FormRow {
  selectedDate: string
  genType: string
  seasonNumber: number
  loading: boolean
  hasPreviewedSuccessfully: boolean
}

const createDefaultRow = (): FormRow => ({
  selectedDate: '',
  genType: '1',
  seasonNumber: 1,
  loading: false,
  hasPreviewedSuccessfully: false,
})

const formRows = ref<FormRow[]>([createDefaultRow()])
// 每一行的预览结果单独存储，按行覆盖
const rowResults = ref<Array<Array<{ key: string, timestamp: number, typeId: number }>>>([[]])

// 全局 TAPD 输入
const globalTapdUrl = ref('')
const globalLoading = ref(false)

// 日历数据
const calendarValue = ref(new Date())
const calendarData = ref<Array<{ key: string, timestamp: number, typeId: number }>>([])
// 每个日期单元格最多展示的事件条数
const maxVisiblePerCell = 3

// 获取指定日期所在周的周一
const getWeekStart = (date: Date) => {
  const dayOfWeek = date.getDay() // 0=周日, 1=周一, ..., 6=周六
  const diff = dayOfWeek === 0 ? 6 : dayOfWeek - 1 // 计算到周一的天数差
  const weekStart = new Date(date)
  weekStart.setDate(date.getDate() - diff)
  weekStart.setHours(0, 0, 0, 0)
  return weekStart
}

// 获取指定日期所在周的周日
const getWeekEnd = (date: Date) => {
  const weekStart = getWeekStart(date)
  const weekEnd = new Date(weekStart)
  weekEnd.setDate(weekStart.getDate() + 6)
  weekEnd.setHours(23, 59, 59, 999)
  return weekEnd
}

// 日历显示范围：基于返回数据时间戳的最早和最晚时间所在周
const calendarRange = computed(() => {
  if (calendarData.value.length === 0) return undefined

  const timestamps = calendarData.value.map(item => item.timestamp)
  const minTimestamp = Math.min(...timestamps)
  const maxTimestamp = Math.max(...timestamps)

  const earliestDate = new Date(minTimestamp * 1000)
  const latestDate = new Date(maxTimestamp * 1000)

  const rangeStart = getWeekStart(earliestDate)
  const rangeEnd = getWeekEnd(latestDate)

  return [rangeStart, rangeEnd]
})

// TAPD URL格式验证正则表达式
const tapdUrlPattern = /^【\d+】--[a-zA-Z_]+=\d+ --user=[\u4e00-\u9fa5a-zA-Z_]+ 【[\u4e00-\u9fa5]+】.+ https?:\/\/.+$/

// URL格式验证（全局）
const isGlobalUrlValid = computed(() => {
  if (!globalTapdUrl.value) return false
  return tapdUrlPattern.test(globalTapdUrl.value.trim())
})

// 表单验证（按行）：期数、日期、类型都必须选择
const isFormValidAt = (index: number) => {
  const row = formRows.value[index]
  if (!row) return false
  return row.seasonNumber > 0 && row.selectedDate !== '' && row.genType !== ''
}

// 是否至少有一行已成功预览
const hasAnyPreviewed = computed(() => formRows.value.some(r => r.hasPreviewedSuccessfully))
// 全局生成按钮可用：只要有行已预览即可点击（TAPD 校验在点击时提示）
const canGenerateGlobal = computed(() => hasAnyPreviewed.value)

// 仅显示时:分，用于日历单格内
const formatTimeHM = (timestamp: number) => {
  const date = new Date(timestamp * 1000)
  const hours = date.getHours().toString().padStart(2, '0')
  const minutes = date.getMinutes().toString().padStart(2, '0')
  return `${hours}:${minutes}`
}

// 时间戳转换为可读格式（含月日与时分）
const formatTimestamp = (timestamp: number) => {
  const date = new Date(timestamp * 1000)
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hours = date.getHours().toString().padStart(2, '0')
  const minutes = date.getMinutes().toString().padStart(2, '0')
  return `${month}月${day}日 ${hours}:${minutes}`
}

// 根据项与新版枚举映射获取调度名称
const getScheduleName = (item: { key: string, timestamp: number, typeId?: number } | undefined) => {
  if (!item || !item.key) return item?.key
  const code = parseInt(item.key)
  const group = item.typeId
  const mappingAny = CombatCalendarScheduleNameMapping as unknown as Record<number, { name: string, mapping: Record<number, string> }>
  if (group && mappingAny[group]?.mapping) {
    const name = mappingAny[group].mapping[code]
    if (name) return name
  }
  // 兜底：尝试在所有分组中查找
  for (const g of Object.keys(mappingAny)) {
    const gid = parseInt(g)
    const map = mappingAny[gid]?.mapping
    if (map && map[code]) return map[code]
  }
  return item.key
}

// 格式化日历单元格的日期显示
const formatDateDisplay = (dateStr: string) => {
  const date = new Date(dateStr)
  const month = date.getMonth() + 1
  const day = date.getDate()
  return `${month}月${day}日`
}

// 获取指定日期的所有调度数据
const getSchedulesForDate = (dateStr: string) => {
  const targetDate = new Date(dateStr)
  const targetDateStr = targetDate.toDateString()
  return calendarData.value.filter(item => {
    const itemDateStr = new Date(item.timestamp * 1000).toDateString()
    return itemDateStr === targetDateStr
  })
}

// 解析日期为年月日
const parseDateParams = (dateStr: string) => {
  const date = new Date(dateStr)
  return {
    year: date.getFullYear(),
    month: date.getMonth() + 1,
    day: date.getDate()
  }
}

// 从 rowResults 重算日历数据（如需跨行去重，这里处理）
const updateCalendarData = () => {
  const keyOf = (e: { key: string, timestamp: number, typeId: number }) => `${e.typeId}__${e.key}__${e.timestamp}`
  const map = new Map<string, { key: string, timestamp: number, typeId: number }>()
  rowResults.value.flat().forEach(e => map.set(keyOf(e), e))
  calendarData.value = Array.from(map.values()).sort((a, b) => a.timestamp - b.timestamp)
}

// 预览（按行）并合并展示
const fetchScheduleDataAt = async (index: number) => {
  if (!http) {
    ElMessage.error('HTTP客户端未初始化')
    return
  }

  const row = formRows.value[index]
  if (!row) return

  row.loading = true

  try {
    const { year, month, day } = parseDateParams(row.selectedDate)
    const url = `http://192.168.9.68:8127/combat_match/gen_match`
    const params = { year, month, day, gen_type: row.genType, serial: row.seasonNumber }

    const response = await http.get(url, { params })

    if (response.data && typeof response.data === 'object') {
      const newData = Object.entries(response.data).map(([key, timestamp]) => ({ key, timestamp: timestamp as number, typeId: parseInt(row.genType) }))
      // 覆盖当前行的预览结果
      if (rowResults.value.length <= index) {
        // 补齐长度（理论上不会触发）
        while (rowResults.value.length <= index) rowResults.value.push([])
      }
      rowResults.value[index] = newData
      updateCalendarData()

      ElMessage.success(`成功获取${newData.length}条调度数据`)

      // 预览成功状态
      row.hasPreviewedSuccessfully = true

      // 设置日历显示的月份为第一个数据的月份
      if (calendarData.value.length > 0) {
        const firstTimestamp = calendarData.value[0].timestamp
        calendarValue.value = new Date(firstTimestamp * 1000)
      }
    } else {
      ElMessage.warning('响应数据格式异常')
    }
  } catch (error) {
    console.error('请求失败:', error)
    ElMessage.error('获取调度数据失败')
    row.hasPreviewedSuccessfully = false
  } finally {
    row.loading = false
  }
}

// 生成（按行）
const genScheduleDataGlobal = async () => {
  if (!http) {
    ElMessage.error('HTTP客户端未初始化')
    return
  }
  if (!hasAnyPreviewed.value) {
    ElMessage.warning('请先预览生成赛程')
    return
  }
  if (!globalTapdUrl.value || globalTapdUrl.value.trim().length === 0) {
    ElMessage.warning('请先填写 TAPD 链接')
    return
  }
  if (!isGlobalUrlValid.value) {
    ElMessage.warning('TAPD 链接格式不正确，请检查')
    return
  }
  globalLoading.value = true
  try {
    const url = `http://192.168.9.68:8127/combat_match/gen_match_xml`
    const params = { tapd: globalTapdUrl.value.trim() }
    const response = await http.get(url, { params })
    if (response.data) {
      ElMessage.success('赛事日程生成成功')
    } else {
      ElMessage.warning('生成响应异常')
    }
  } catch (error) {
    console.error('生成请求失败:', error)
    ElMessage.error('赛事日程生成失败')
  } finally {
    globalLoading.value = false
  }
}

// 赛事类型选项：排除其他行已选类型，但保留当前行现有选择
const getAvailableTypes = (index: number) => {
  const current = formRows.value[index]?.genType
  const used = new Set(formRows.value.map((r, i) => (i === index ? undefined : r.genType)).filter(Boolean) as string[])
  return baseTypeOptions.filter(opt => opt.value === current || !used.has(opt.value))
}

// 是否还有可用的赛事类型可继续新增
const hasMoreTypeOptions = () => {
  const used = new Set(formRows.value.map(r => r.genType))
  return baseTypeOptions.some(opt => !used.has(opt.value))
}

// 添加新行（直到类型用尽）
const addRow = () => {
  const used = new Set(formRows.value.map(r => r.genType))
  const candidate = baseTypeOptions.find(opt => !used.has(opt.value))
  if (!candidate) return
  const next = createDefaultRow()
  next.genType = candidate.value
  formRows.value.push(next)
  rowResults.value.push([])
}

// 表单变化重置对应行的预览状态
watch(formRows, (newRows, oldRows) => {
  newRows.forEach((row, i) => {
    const oldRow = oldRows?.[i]
    if (!oldRow) return
    if (row.selectedDate !== oldRow.selectedDate || row.genType !== oldRow.genType || row.seasonNumber !== oldRow.seasonNumber) {
      row.hasPreviewedSuccessfully = false
    }
  })
}, { deep: true })

</script>

<style scoped>
.calendar-schedule {
  padding: 20px;
}

.control-panel {
  margin-bottom: 30px;
  padding: 20px;
  background-color: #f5f7fa;
  border-radius: 8px;
}

.form-label {
  display: inline-block;
  width: 96px;
  white-space: nowrap;
  color: #606266;
}

/* URL输入框验证状态样式 */
:deep(.url-valid .el-input__wrapper) {
  border-color: #67c23a;
  box-shadow: 0 0 0 1px #67c23a inset;
}

:deep(.url-invalid .el-input__wrapper) {
  border-color: #f56c6c;
  box-shadow: 0 0 0 1px #f56c6c inset;
}

.calendar-container {
  margin-bottom: 20px;
}

.calendar-cell {
  height: 100px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding: 6px;
}

.calendar-cell p {
  margin: 0 0 6px 0;
  font-size: 16px;
  font-weight: 500;
}

.calendar-cell .is-selected {
  color: #1989fa;
  font-weight: bold;
}

/* 多事件列表：限制单格内展示数量，剩余由 +N 承载 */
.schedule-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  overflow: hidden;
}

.schedule-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
}

.schedule-item .el-tag,
.schedule-list .el-tag {
  font-size: 11px;
  padding: 3px 6px;
  border-radius: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  line-height: 1.3;
  font-weight: 500;
}

/* 悬浮弹出列表样式 */
.popover-list {
  max-height: 240px;
  overflow-y: auto;
}

.popover-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 12px;
  line-height: 1.4;
  padding: 4px 0;
  border-bottom: 1px dashed #ebeef5;
}

.popover-item:last-child {
  border-bottom: none;
}

.schedule-name {
  margin-right: 8px;
}

.schedule-time {
  color: #909399;
}

/* 日历样式优化 */
:deep(.el-calendar-table .el-calendar-day) {
  height: 100px;
  padding: 0;
}

:deep(.el-calendar__header) {
  padding: 12px 20px;
  border-bottom: 1px solid #ebeef5;
}

:deep(.el-calendar__button-group) {
  margin-left: auto;
}
</style>
